use std::collections::HashMap;

#[derive(Debug)]
pub struct GrammarScope<'scope, 'input, Item: Clone> {
    parent: Option<&'scope GrammarScope<'scope, 'input, Item>>,
    symbols: HashMap<&'input str, Item>,
}

impl<'scope, 'input, Item: Clone> Default for GrammarScope<'scope, 'input, Item> {
    fn default() -> Self {
        Self {
            parent: None,
            symbols: HashMap::new(),
        }
    }
}

impl<'scope, 'input, Item: Clone> GrammarScope<'scope, 'input, Item> {
    pub fn new(parent: &'scope GrammarScope<'scope, 'input, Item>) -> Self {
        Self {
            parent: Some(parent),
            symbols: HashMap::new(),
        }
    }

    pub fn find_symbol(&self, name: &str) -> Option<Item> {
        self.symbols
            .get(name)
            .cloned()
            .or_else(|| self.parent.and_then(|parent| parent.find_symbol(name)))
    }

    pub fn insert_symbol(&mut self, name: &'input str, symbol: Item) {
        if self.symbols.insert(name, symbol).is_some() {
            panic!("Symbol already inserted: {}", name)
        }
    }
}
